/*
** config.hh
** Login : <David@sandrock.lrde.epita.fr>
** Started on  Mon Apr  7 13:42:04 2003 David Lesage
** $Id: config.hh 44 2003-04-11 16:07:39Z burrus_n $
** 
** Copyright (C) 2003 David Lesage
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
** 
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#ifndef   	CONFIG_HH_
# define   	CONFIG_HH_

# include <cassert>
# include <sstream>

# include "initializer.hh"
# include "varset.hh"

namespace evz
{

  /*----------.
  | Config<T> |
  `----------*/

  //! Represent a particular configuration on a VarSet.
  /*! 
    Given a list of realisation, Config transforms it into a list
    of variable values id. The list of realisation must be defined on
    the same order than the variables were inserted into the varset,
    and must give a realisation for every variable.
  */

  template <class T>
  class Config
  {
  public:
    typedef std::list<unsigned> list_type;
    typedef list_type::iterator iterator;
    typedef list_type::const_iterator const_iterator;
    typedef list_type::reverse_iterator reverse_iterator;
    typedef list_type::const_reverse_iterator const_reverse_iterator;

  private:
    typedef Initializer<T> initializer_type;

  public:
    Config(const VarSet<T>& vset, 
	   const std::list<T>& values)
      : vset_(vset)
    {
      init_from_list(values);
    }
    
    Config(const VarSet<T>& vset, 
	   const initializer_type& values)
      : vset_(vset)
    {
      init_from_list(values.get_elts());
    }

    // Return a starter for the list of values.
    static initializer_type start()
    {
      return initializer_type();
    }

    // Return the list of variable values.
    const list_type& get_values(void) const
    {
      return values_;
    }

    // Return a string associated to the config. This requires T to
    // have a stream operator.
    std::string to_string(void) const
    {
      std::string res;
      res += "( ";
      
      unsigned index = 0;
      for (const_iterator val = values_.begin();
	   val != values_.end(); 
	   ++val, ++index)
	{
	  const Var<T>& v = vset_.get_nth_var(index);
	  std::ostringstream ost;
	  ost << v.get_real(*val); 
	  res += ost.str();
	  if (index < vset_.get_nb_vars() - 1)
	    res += ", ";
	}
      res += " )";
      return res;
    }

  private:
    void init_from_list(const std::list<T>& values)
    {
      //assert(values.size() == vset_.get_nb_vars());
      
      unsigned cpt = 0;
      
      for (typename std::list<T>::const_iterator i = values.begin();
	   i != values.end(); 
	   ++i, ++cpt)
	{
	  //assert(vset_.get_nth_var(cpt).has_real(*i));
	  values_.push_back(vset_.get_nth_var(cpt).get_real_id(*i));
	}
    }

  private:
    const VarSet<T>& vset_;
    list_type values_;
  };

  template<class T>
  inline std::ostream&
  operator<<(std::ostream& o, const Config<T>& c)
  {    
    o << c.to_string();
    return o;
  }

} // end of evz

#endif	    /* !CONFIG_HH_ */
